package com.gel.aiagent.agent;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.gel.aiagent.agent.model.AgentState;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.ToolResponseMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.model.tool.ToolExecutionResult;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.chat.messages.UserMessage;

import java.util.List;
import java.util.stream.Collectors;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class ToolCallAgent extends ReActAgent{
    //可用的工具
    private final ToolCallback[] availableTools;

    //保存工具的响应结果
    private ChatResponse toolCallChatResponse;
    //工具管理者
    private ToolCallingManager toolCallingManager;

    //禁用SpringAi内置的工具调用机制们自己维护选项和上下文
    private final ChatOptions chatOptions;

    public ToolCallAgent(ToolCallback[] availableTools) {
        super();
        this.availableTools = availableTools;
        this.toolCallingManager=ToolCallingManager.builder().build();
        this.chatOptions= DashScopeChatOptions.builder()
                .withProxyToolCalls( true)
                .build();
    }

    /*处理当前状态决定是否下一步行动*/
    @Override
    public boolean think() {
        //检验提示词，凭借提示词
        if(getNextStepPrompt()!=null&&!getNextStepPrompt().isEmpty()){
            UserMessage userMessage=new UserMessage(getNextStepPrompt());
            getMessageList().add(userMessage);
        }
        List<Message> massageList=getMessageList();
        Prompt prompt = new Prompt(massageList,chatOptions);

        //获取带工具选型的响应
        try {
            ChatResponse chatResponse = getChatClient().prompt(prompt)
                    .system(getSystemPrompt())
                    .tools(availableTools)
                    .call()
                    .chatResponse();
            //记录响应，用于act
            this.toolCallChatResponse=chatResponse;
            AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
            //输出提示信息
            String result = assistantMessage.getText();

            List<AssistantMessage.ToolCall> toolCallList = assistantMessage.getToolCalls();
            log.info(getName()+"思考了"+result);
            log.info(getName()+"选择了"+toolCallList.size()+"个工具来使用");
            String toolCallInfo = toolCallList.stream()
                    .map(toolCall -> String.format("工具名称: %s,参数：%s", toolCall.name(), toolCall.arguments()))
                           .collect(Collectors.joining("\n"));
            log.info(toolCallInfo);
            //只有不调用工具时才记录助手消息
            if(toolCallList.isEmpty()){
                getMessageList().add(assistantMessage);
                return  false;
            }else {
                return  true;
            }
        } catch (Exception e) {
            log.error(getName() + "的思考过程遇到了问题：" + e.getMessage());
            getMessageList().add(new AssistantMessage("处理时遇到了错误：" + e.getMessage()));
            return false;
        }
    }

    @Override
    public String act() {
        if(!toolCallChatResponse.hasToolCalls()){
            return "没有工具调用";
        }
        //调用工具
        Prompt prompt = new Prompt(getMessageList(),chatOptions);
        ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, toolCallChatResponse);
        //记录上下文
        setMessageList(toolExecutionResult.conversationHistory());
        //当前工具的调用结果
        ToolResponseMessage toolResponseMessage = (ToolResponseMessage) CollUtil.getLast(toolExecutionResult.conversationHistory());
        String results = toolResponseMessage.getResponses().stream()
                .map(response -> response.name() + "完成了他的任务！结果：" + response.responseData())
                .collect(Collectors.joining("\n"));
        //判断是否使用了终止工具
        boolean terminateToolCall = toolResponseMessage.getResponses().stream()
                .anyMatch(response -> response.name().equals("doTerminate"));
        if(terminateToolCall){
            setState(AgentState.FINISHED);
        }
        log.info(results);
        return  results;
    }
}
